// SPDX-FileCopyrightText: Copyright 2023 CitruS Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

package com.fanwj.citrus.applets.keyboard

import android.content.Context
import android.os.Handler
import android.os.Looper
import android.view.KeyEvent
import android.view.View
import android.view.WindowInsets
import android.view.inputmethod.InputMethodManager
import androidx.annotation.Keep
import androidx.core.view.ViewCompat
import com.fanwj.citrus.aidl.IFrontend
import com.fanwj.citrus.NativeLibrary
import com.fanwj.citrus.R
import com.fanwj.citrus.applets.keyboard.ui.KeyboardDialogFragment
import java.util.concurrent.locks.LockSupport

typealias KeyboardConfig = IFrontend.KeyboardConfig

typealias KeyboardData = IFrontend.KeyboardData

// Corresponds to Service::AM::Applets::SwkbdResult
typealias SwkbdResult = IFrontend.SwkbdResult

object SoftwareKeyboard {

    private fun executeInlineImpl(config: KeyboardConfig) {
        val emulationActivity = NativeLibrary.sEmulationActivity.get()

        val overlayView = emulationActivity!!.findViewById<View>(R.id.surface_input_overlay)
        val im =
            overlayView.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        im.showSoftInput(overlayView, InputMethodManager.SHOW_FORCED)

        // There isn't a good way to know that the IMM is dismissed, so poll every 500ms to submit inline keyboard result.
        val handler = Handler(Looper.myLooper()!!)
        val delayMs = 500
        handler.postDelayed(
            object : Runnable {
                override fun run() {
                    val insets = ViewCompat.getRootWindowInsets(overlayView)
                    val isKeyboardVisible = insets!!.isVisible(WindowInsets.Type.ime())
                    if (isKeyboardVisible) {
                        handler.postDelayed(this, delayMs.toLong())
                        return
                    }

                    // No longer visible, submit the result.
                    NativeLibrary.submitInlineKeyboardInput(KeyEvent.KEYCODE_ENTER)
                }
            },
            delayMs.toLong()
        )
    }

    fun executeNormal(config: KeyboardConfig): KeyboardData {
        val result = arrayOf(KeyboardData())
        val thread = Thread.currentThread()
        NativeLibrary.sEmulationActivity.get()?.run {
            runOnUiThread {
                val fragment = KeyboardDialogFragment(config) { data ->
                    result[0] = data
                    LockSupport.unpark(thread)
                }
                fragment.show(supportFragmentManager, "KeyboardDialogFragment")
            }
        }
        LockSupport.park()
        return result[0]
    }

    fun executeInline(config: KeyboardConfig) {
        NativeLibrary.sEmulationActivity.get()?.run {
            runOnUiThread { executeInlineImpl(config) }
        }
    }

    // Corresponds to Service::AM::Applets::SwkbdType
    enum class SwkbdType {
        Normal,
        NumberPad,
        Qwerty,
        Unknown3,
        Latin,
        SimplifiedChinese,
        TraditionalChinese,
        Korean
    }

    // Corresponds to Service::AM::Applets::SwkbdPasswordMode
    enum class SwkbdPasswordMode {
        Disabled,
        Enabled
    }
}